package com.ziyueyuwen.xiniao.service.impl;


import com.suyeer.cache.RedisUtil;
import com.ziyueyuwen.xiniao.bean.ZyClassLessonInfo;
import com.ziyueyuwen.xiniao.bean.ZyLessonMessageTask;
import com.ziyueyuwen.xiniao.bean.ZyUser;
import com.ziyueyuwen.xiniao.bean.homework.SubjectQuestionExistElementData;
import com.ziyueyuwen.xiniao.bean.vo.ZyLessonVO;
import com.ziyueyuwen.xiniao.dao.ZyClassLessonInfoMapper;
import com.ziyueyuwen.xiniao.dao.ZyLessonMessageTaskMapper;
import com.ziyueyuwen.xiniao.enums.LessonModuleEnum;
import com.ziyueyuwen.xiniao.enums.MessageTypeEnum;
import com.ziyueyuwen.xiniao.service.MessageTaskService;
import com.ziyueyuwen.xiniao.service.SubjectQuestionService;
import com.ziyueyuwen.xiniao.service.UserService;
import com.ziyueyuwen.xiniao.service.WxMessageService;
import com.ziyueyuwen.xiniao.util.DateUtil;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

import static com.ziyueyuwen.xiniao.enums.MessageTypeEnum.*;

/**
 * @author wancheng  on 2018/12/20.
 */
@Service
public class MessageTaskServiceImpl implements MessageTaskService {

    private static final Logger logger = LoggerFactory.getLogger(MessageTaskServiceImpl.class);
    private static final String HAS_TASK_KEY = "MESSAGE_HAS_TASK";
    private static final Integer TWO_DAY_CHECK = 2 * 24;
    private final Integer LESSON_BEFORE_START_CHECK = 20;
    @Autowired
    ZyLessonMessageTaskMapper zyLessonMessageTaskMapper;
    @Autowired
    ZyClassLessonInfoMapper zyClassLessonInfoMapper;
    @Autowired
    WxMessageService wxMessageService;
    @Autowired
    UserService userService;
    @Autowired
    SubjectQuestionService subjectQuestionService;

    @Override
    public Boolean ifHasTask(Integer lessonId, MessageTypeEnum typeEnum) {
        ZyLessonVO lessonVO = zyClassLessonInfoMapper.getLessonClassAndCourse(lessonId);
        Integer subjectId = lessonVO.getCourse().getSubjectId();
        Integer lessonIndex = lessonVO.getLessonIndex();
        HashMap<Integer, SubjectQuestionExistElementData> data = subjectQuestionService.getSubjectQuestionExistElementDataInfoBySubjectId(subjectId);
        SubjectQuestionExistElementData existElementData = data.get(lessonIndex);
        if(existElementData == null){
            return false;
        }
        switch (typeEnum){
            case MESSAGE_LESSON_INFLATED:
                return existElementData.getIfHavePreviewInfo();
            case MESSAGE_LESSON_URL_SUMMARIZE:
                return existElementData.getIfHaveSummaryInfo();
            case MESSAGE_LESSON_HOMEWORK:
                return existElementData.getIfHaveQuestionInfo();
            case MESSAGE_LESSON_EXPANSION:
                return existElementData.getIfHaveExpandInfo();
            default:
                return false;
        }
    }

    @Override
    public void lessonPreviewForTowDay(Date before, Date after) {
       try{
           before = DateUtils.addHours(before, 24 * 2);
           after = DateUtils.addHours(after, 24 * 2);
           List<ZyClassLessonInfo> lessonInfos = zyClassLessonInfoMapper.getBeginTimeBetween(before, after);
           lessonInfos.forEach(
                   l -> {
                       ZyClassLessonInfo previous = zyClassLessonInfoMapper.getPreviousLesson(l.getId());
                       if (previous != null && DateUtil.caleHour(previous.getEndTime(), l.getBeginTime(), true) < TWO_DAY_CHECK) {
                           return;
                       }
                       if (!ifHasTask(l.getId(), MESSAGE_LESSON_INFLATED)) {
                           return;
                       }
                       ZyLessonMessageTask task = insertMessageTask(l.getId(), "课前48小时发送课前提醒", MESSAGE_LESSON_INFLATED, true);
                       List<ZyUser> students = userService.getStudents(l.getClassId());
                       students.forEach(
                               s -> {
                                   wxMessageService.sendClassRemindInflated(s.getUserAccount(), l.getId(), task.getId());
                                   logger.info("课前48小时发送课前提醒,参数:学生={},课节={},task={}",s.getUserAccount(), l.getId(), task.getId());
                               }
                       );
                   }
           );
       }catch (Exception e){
           e.printStackTrace();
       }
    }

    @Override
    public void lessonPreviewForTwentyHour(Date before, Date after) {
        try{
            before = DateUtils.addHours(before, 20);
            after = DateUtils.addHours(after, 20);
            List<ZyClassLessonInfo> lessonInfos = zyClassLessonInfoMapper.getBeginTimeBetween(before, after);
            lessonInfos.forEach(
                    l -> {
                        ZyClassLessonInfo previous = zyClassLessonInfoMapper.getPreviousLesson(l.getId());

                        if (previous != null) {
                            Integer hour = DateUtil.caleHour(previous.getEndTime(), l.getBeginTime(), true);
                            if (hour >= TWO_DAY_CHECK || hour <= LESSON_BEFORE_START_CHECK){
                                return;
                            }
                        }else{
                            return;
                        }
                        if (!ifHasTask(l.getId(), MESSAGE_LESSON_INFLATED)) {
                            return;
                        }
                        ZyLessonMessageTask task = insertMessageTask(l.getId(), "课前20小时发送课前提醒", MESSAGE_LESSON_INFLATED, true);
                        List<ZyUser> students = userService.getStudents(l.getClassId());
                        students.forEach(
                                s -> {
                                    wxMessageService.sendClassRemindInflated(s.getUserAccount(), l.getId(), task.getId());
                                    logger.info("课前20小时发送课前提醒,参数:学生={},课节={},task={}",s.getUserAccount(), l.getId(), task.getId());
                                }
                        );
                    }
            );
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void lessonBeforeOneHour(Date before, Date after) {
        try {
            before = DateUtils.addHours(before, 1);
            after = DateUtils.addHours(after, 1);
            List<ZyClassLessonInfo> lessonInfos = zyClassLessonInfoMapper.getBeginTimeBetween(before, after);
            lessonInfos.forEach(
                    l -> {
                        ZyLessonMessageTask task = insertMessageTask(l.getId(), "课前1小时提醒", MESSAGE_LESSON_BEFORE_ONE_HOUR, true);
                        List<ZyUser> students = userService.getStudents(l.getClassId());
                        students.forEach(
                                s -> {
                                    wxMessageService.sendLessonBeforeOneHour(s.getUserAccount(), l.getId(), task.getId());
                                    logger.info("课前1小时提醒,参数:学生={},课节={},task={}",s.getUserAccount(), l.getId(), task.getId());
                                }
                        );
                    }
            );
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void lessonBeforeFifteenMinute(Date before, Date after) {
        try {
            before = DateUtils.addMinutes(before, 15);
            after = DateUtils.addMinutes(after, 15);
            List<ZyClassLessonInfo> lessonInfos = zyClassLessonInfoMapper.getBeginTimeBetween(before, after);
            lessonInfos.forEach(
                    l -> {
                        ZyLessonMessageTask task = insertMessageTask(l.getId(), "课前15分钟提醒", MESSAGE_LESSON_BEFORE_FIFTEEN_MINUTE, true);
                        List<ZyUser> students = userService.getStudents(l.getClassId());
                        students.forEach(
                                s -> {
                                    wxMessageService.sendLessonBeforeFifteenMinute(s.getUserAccount(), l.getId(), task.getId());
                                    logger.info("课前15分钟提醒,参数:学生={},课节={},task={}",s.getUserAccount(), l.getId(), task.getId());
                                }
                        );
                    }
            );
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void lessonHomework(Date before, Date after) {
        try {
            before = DateUtils.addMinutes(before, -10);
            after = DateUtils.addMinutes(after, -10);
            List<ZyClassLessonInfo> lessonInfos = zyClassLessonInfoMapper.getEndTimeBetween(before, after);
            lessonInfos.forEach(
                    l -> {
                        if (!ifHasTask(l.getId(), MESSAGE_LESSON_HOMEWORK)) {
                            return;
                        }
                        ZyLessonMessageTask task = insertMessageTask(l.getId(), "课后作业", MESSAGE_LESSON_HOMEWORK, true);
                        List<ZyUser> students = userService.getStudents(l.getClassId());
                        students.forEach(
                                s -> {
                                    wxMessageService.sendLessonHomework(s.getUserAccount(), l.getId(), task.getId());
                                    logger.info("课后作业,参数:学生={},课节={},task={}",s.getUserAccount(), l.getId(), task.getId());
                                }
                        );
                    }
            );
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void lessonSummarize(Date before, Date after) {
        try {
            before = DateUtils.addMinutes(before, -10);
            after = DateUtils.addMinutes(after, -10);
            List<ZyClassLessonInfo> lessonInfos = zyClassLessonInfoMapper.getEndTimeBetween(before, after);
            lessonInfos.forEach(
                    l -> {
                        if (!ifHasTask(l.getId(), MESSAGE_LESSON_URL_SUMMARIZE)) {
                            return;
                        }
                        ZyLessonMessageTask task = insertMessageTask(l.getId(), "课后总结", MessageTypeEnum.MESSAGE_LESSON_URL_SUMMARIZE, true);
                        List<ZyUser> students = userService.getStudents(l.getClassId());
                        students.forEach(
                                s -> {
                                    wxMessageService.sendLessonSummarize(s.getUserAccount(), l.getId(), task.getId());
                                    logger.info("课后总结,参数:学生={},课节={},task={}",s.getUserAccount(), l.getId(), task.getId());
                                }
                        );
                    }
            );
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void lessonExpansion(Date before, Date after) {
        try {
            before = DateUtils.addMinutes(before, -10);
            after = DateUtils.addMinutes(after, -10);
            List<ZyClassLessonInfo> lessonInfos = zyClassLessonInfoMapper.getEndTimeBetween(before, after);
            lessonInfos.forEach(
                    l -> {
                        if (!ifHasTask(l.getId(), MESSAGE_LESSON_EXPANSION)) {
                            return;
                        }
                        ZyLessonMessageTask task = insertMessageTask(l.getId(), "课后拓展", MessageTypeEnum.MESSAGE_LESSON_EXPANSION, false);
                        List<ZyUser> students = userService.getStudents(l.getClassId());
                        students.forEach(
                                s -> {
                                    wxMessageService.saveLessonExpansion(s.getUserAccount(), l.getId(), task.getId());
                                    logger.info("课后拓展,参数:学生={},课节={},task={}",s.getUserAccount(), l.getId(), task.getId());
                                }
                        );
                    }
            );
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void lessonReplay(Date before, Date after) {
        try {
            before = DateUtils.addMinutes(before, -10);
            after = DateUtils.addMinutes(after, -10);
            List<ZyClassLessonInfo> lessonInfos = zyClassLessonInfoMapper.getEndTimeBetween(before, after);
            lessonInfos.forEach(
                    l -> {
                        ZyLessonMessageTask task = insertMessageTask(l.getId(), "课节回放", MessageTypeEnum.MESSAGE_LESSON_URL_REPLAY, false);
                        List<ZyUser> students = userService.getStudents(l.getClassId());
                        students.forEach(
                                s -> {
                                    wxMessageService.sendLessonReplay(s.getUserAccount(), l.getId(), task.getId());
                                    logger.info("课节回放,参数:学生={},课节={},task={}",s.getUserAccount(), l.getId(), task.getId());
                                }
                        );
                    }
            );
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void lessonHomeworkUnCommit(Date before, Date after) {
        try {
            before = DateUtils.addHours(before, -24 * 2);
            after = DateUtils.addHours(after, -24 * 2);
            List<ZyClassLessonInfo> lessonInfos = zyClassLessonInfoMapper.getEndTimeBetween(before, after);
            lessonInfos.forEach(
                    l -> {
                        ZyLessonMessageTask task = insertMessageTask(l.getId(), "课后48小时作业未提交", MessageTypeEnum.MESSAGE_LESSON_HOMEWORK_UN_COMMIT, true);
                        List<ZyUser> students = userService.getStudents(l.getClassId());
                        students.forEach(
                                s -> {
                                    wxMessageService.sendLessonHomeworkUnCommit(s.getUserAccount(), l.getId(), task.getId());
                                    logger.info("课后48小时作业未提交,参数:学生={},课节={},task={}",s.getUserAccount(), l.getId(), task.getId());
                                }
                        );
                    }
            );
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public List<ZyLessonMessageTask> getByCourseIdAndLessonIndex(Integer courseId, Integer lessonIndex, LessonModuleEnum lessonModuleEnum) {
        MessageTypeEnum type = null;
        switch (lessonModuleEnum){
            case PREVIEW:
                type = MESSAGE_LESSON_INFLATED;
                break;
            case HOMEWORK:
                type = MESSAGE_LESSON_HOMEWORK;
                break;
            case SUMMARY:
                type = MESSAGE_LESSON_URL_SUMMARIZE;
                break;
            case EXPAND:
                type = MESSAGE_LESSON_EXPANSION;
                break;
            default:
                break;
        }
        if (type == null){
            return null;
        }
        List<ZyLessonMessageTask> tasks = zyLessonMessageTaskMapper.getByCourseIdAndLessonIndex(courseId,lessonIndex,type);
        return tasks;
    }

    private ZyLessonMessageTask insertMessageTask(Integer lessonId, String desc, MessageTypeEnum typeEnum, Boolean ifNeedSend) {
        ZyLessonMessageTask param = new ZyLessonMessageTask();
        param.setLessonId(lessonId);
        param.setType(typeEnum);
        ZyLessonMessageTask task = zyLessonMessageTaskMapper.selectOne(param);
        Date date = new Date();
        if (task == null) {
            task = new ZyLessonMessageTask();
            task.setIfNeedSend(ifNeedSend);
            task.setIfExecute(true);
            task.setType(typeEnum);
            task.setLessonId(lessonId);
            task.setCreateTime(date);
            task.setDescription(desc);
            task.setSendTime(date);
            zyLessonMessageTaskMapper.insertUseGeneratedKeys(task);
        } else {
            task.setIfExecute(true);
            task.setIfNeedSend(ifNeedSend);
            task.setSendTime(date);
            zyLessonMessageTaskMapper.updateByPrimaryKeySelective(task);
        }
        return task;
    }
}
